#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <iomanip>

#include "Ephemeris.hpp"
#include "SatTime.hpp"

#pragma region parseSp3 定义

/// <summary>
/// 获取卫星系统缩写
/// </summary>
std::string getSatSystemA(SatSystem system);

/// <summary>
/// 获取卫星系统
/// </summary>
std::string getSatSystem(const std::string& satSystem);

/// <summary>
/// 获取时间间隔
/// </summary>
double getTimeStep(const std::string& line);

///  <summary>
/// 获取卫星位置
/// </summary>
SatTime getTime(const std::string& line);

///  <summary>
/// 获取卫星位置
/// </summary>
SatPosition getSatLocation(const std::string& line);

///  <summary>
/// 保存卫星位置
/// </summary>
void saveSatFile(const std::vector<SatPosition>&satLocation, const char*outFileName);

#pragma endregion


#pragma region parseSp3 实现
std::string getSatSystemA(SatSystem system)
{
    switch (system)
    {
        case SatSystem::GPS:
            return "G ";
        case SatSystem::Glonass:
            return "R";
        case SatSystem::Galileo:
            return "E";
        case SatSystem::BeiDou:
            return "C";
        default:
            return "UNKNOWN";
    }
}

std::string getSatSystem(const std::string& satSystem)
{
    std::vector<SatSystem>result;
    if(satSystem == "GPS")
        result.push_back(SatSystem::GPS);
    else if(satSystem == "GLO")
        result.push_back(SatSystem::Glonass);
    else if(satSystem == "GAL")
        result.push_back(SatSystem::Galileo);
    else if(satSystem == "BDS")
        result.push_back(SatSystem::BeiDou);
    else if(satSystem == "BDGPS")
    {
        result.push_back(SatSystem::GPS);
        result.push_back(SatSystem::BeiDou);
    }

    std::string sys;
    for(auto system:result)
        sys+=getSatSystemA(system);
    return sys;
}

double getTimeStep(const std::string& line)
{
    double timeStep;
    std::istringstream iss(line.substr(2));
    iss >> timeStep;
    iss >> timeStep;
    iss >> timeStep;
    return timeStep;
}

SatTime getTime(const std::string& line)
{
    std::istringstream iss(line.substr(1));

    SatTime satTime{};
    iss >> satTime.year >> satTime.month >> satTime.day >> satTime.hour >> satTime.minute >> satTime.second;

    return satTime;
}

SatPosition getSatLocation(const std::string& line)
{
    std::istringstream iss(line.substr(1)); // 去掉 'C'
    std::string satId;
    double x, y, z;
    iss>>satId;
    iss >> x >> y >> z;

    SatPosition tempSatlocation;
    tempSatlocation.satId=satId;
    tempSatlocation.spatialCoords.x=x*1000;
    tempSatlocation.spatialCoords.y=y*1000;
    tempSatlocation.spatialCoords.z=z*1000;
    return tempSatlocation;
}

void saveSatFile(const std::vector<SatPosition>&satLocation, const char*outFileName)
{
    std::ofstream outFile(outFileName);
    outFile << std::fixed << std::setprecision(3);
    for(const auto& coord:satLocation)
    {
        outFile<<coord.satId<<" "
               <<coord.spatialCoords.x<<" "
               <<coord.spatialCoords.y<<" "
               <<coord.spatialCoords.z<<std::endl;
    }
    outFile.close();
}

#pragma endregion


void parseSp3File(const char* satFileName, const char*outFilePath,const char* satSystem,double timeStep)
{
    auto satSystems= getSatSystem(satSystem);
    std::ifstream file(satFileName);

    if (!file.is_open()) {
        std::cerr << "Failed to open file.\n";
        return;
    }

    std::string line;
    std::vector<SatPosition> satPositions;
    SatTime preTime{};

    while (std::getline(file, line))
    {
        if (line.empty()) continue;

        // 判断是否是时间行
        if(line[0] == '*')
        {
            SatTime currentTime=getTime(line);
            if (!satPositions.empty())
            {
                //保存文件
                std::string outFileName = std::string(outFilePath) + "/" + preTime.toString();
                saveSatFile(satPositions, outFileName.c_str());
                satPositions.clear();

                // 过一个时间间隔
                if(abs(preTime-currentTime)<timeStep)
                {
                    std::string tempLine;
                    while (std::getline(file, tempLine))
                    {
                        if (tempLine[0] == '*')
                        {
                            currentTime=getTime(tempLine);
                            if(abs(preTime-currentTime)>=timeStep)
                                break;
                        }
                    }
                    line=tempLine;
                }
                preTime=currentTime;
            }
            else
                preTime=currentTime;
        }
        // 否则是卫星坐标行
        else if(line[0]=='P')
        {
            if(satSystems.find(line[1]) == std::string::npos)
                continue;
            SatPosition tempSatlocation= getSatLocation(line);
            satPositions.push_back(tempSatlocation);
        }
        // 获取时间步长
        else if(timeStep==0&&line.size()>2&&line[0]=='#'&&line[1]=='#')
        {
            timeStep=getTimeStep(line);
        }
        else
            continue;
    }
}


void loadSatFile(const char*satFileName,SpatialCoord *&satSpatialCoords,int &satCount)
{
    std::ifstream file(satFileName);
    if (!file.is_open()) {
        std::cerr << "Don't open the file" << std::endl;
        return;
    }

    std::vector<SpatialCoord>tempSatCoords;

    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        std::string label;
        double x, y, z;
        if (iss >> label >> x >> y >> z)
        {
            SpatialCoord tempCoord{};
            tempCoord.x = x;
            tempCoord.y = y;
            tempCoord.z = z;
            tempSatCoords.push_back(tempCoord);
        }
    }
    file.close();

    satCount=(int)tempSatCoords.size();
    satSpatialCoords=new SpatialCoord[satCount];
    for(int i=0;i<satCount;i++)
        satSpatialCoords[i]=tempSatCoords[i];
}